package top.jacktgq.wait_notify.producer_consumer;

import java.util.LinkedList;

import top.jacktgq.utils.LogUtils;
import top.jacktgq.utils.Sleeper;

/**
 * 
 * @Title: Producer_ConsumerDemo.java 
 * @Package top.jacktgq.wait_notify.producer_consumer 
 * @Description:异步模式之 生产者、消费者案例
 * @author CandyWall   
 * @date 2020年11月1日 下午10:38:29 
 * @version V1.0
 */
public class Producer_ConsumerDemo {
	public static void main(String[] args) {
		boolean isRunning = true; 
		MessageQueue messageQueue = new MessageQueue(5);		
		for(int i = 0; i < 3; i++) {
			int id = i;
			new Thread(() -> {
				while(isRunning) {
					Message message = new Message(id * 100, "你好");
					LogUtils.log("Producer_ConsumerDemo", " 生产了一条消息，内容为：" + message + "，目前消息队列中的消息数量为：" + messageQueue.getSize());
					messageQueue.put(message);
 					Sleeper.sleep(1);
				}
			}, "生产者" + i).start();
		}
		for(int i = 0; i < 4; i++) {
			new Thread(() -> {
				while(isRunning) {
					Message message = messageQueue.take();
					LogUtils.log("Producer_ConsumerDemo", " 消费了一条消息 ，内容为：" + message + "，目前消息队列中的消息数量为：" + messageQueue.getSize());
					Sleeper.sleep(2);
				}
			}, "消费者" + i).start();
		}
	}
}

//消息队列，java线程之间通信
class MessageQueue {
	//消息的队列集合
	private LinkedList<Message> messageList = new LinkedList<Message>();
	//队列容量
	private int capcity;
	public MessageQueue(int capcity) {
		this.capcity = capcity;
	}

	//获取消息
	public Message take() {
		synchronized (messageList) {
			while(messageList.isEmpty()) {
				try {
					LogUtils.log("MessageQueue", " 队列为空，消费者线程等待");
					messageList.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			//从队列头部获取消息并返回
			Message message = messageList.removeFirst();
			messageList.notifyAll();
			return message;
		}
	}
	
	//存入消息
	public void put(Message message) {
		synchronized (messageList) {
			while(messageList.size() == capcity) {
				try {
					LogUtils.log("MessageQueue", " 队列满了，生产者线程等待");
					messageList.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			//将消息加入队列尾部
			messageList.addLast(message);
			messageList.notifyAll();
		}
	}
	
	public int getSize() {
		return messageList.size();
	}
}

final class Message {
	private int id;
	private Object value;
	public int getId() {
		return id;
	}
	public Object getValue() {
		return value;
	}
	public Message(int id, Object value) {
		super();
		this.id = id;
		this.value = value;
	}
	@Override
	public String toString() {
		return "Message [id=" + id + ", value=" + value + "]";
	}
	
}
